home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1984,1985,1989,1994 Mark Nudelman
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice in the documentation and/or other materials provided with
- * the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
- /*
- * Functions to define the character set
- * and do things specific to the character set.
- */
-
- #include "less.h"
- #if HAVE_LOCALE
- #include <locale.h>
- #include <ctype.h>
- #endif
-
- /*
- * Predefined character sets,
- * selected by the LESSCHARSET environment variable.
- */
- struct charset {
- char *name;
- char *desc;
- } charsets[] = {
- { "ascii", "8bcccbcc18b95.b" },
- { "latin1", "8bcccbcc18b95.33b." },
- { "dos", "8bcccbcc12bc5b95.98b.b" },
- { "koi8-r", "8bcccbcc18b95.b128." },
- { NULL }
- };
-
- #define IS_BINARY_CHAR 01
- #define IS_CONTROL_CHAR 02
-
- static char chardef[256];
- static char *binfmt = NULL;
- public int binattr = AT_STANDOUT;
-
-
- /*
- * Define a charset, given a description string.
- * The string consists of 256 letters,
- * one for each character in the charset.
- * If the string is shorter than 256 letters, missing letters
- * are taken to be identical to the last one.
- * A decimal number followed by a letter is taken to be a
- * repetition of the letter.
- *
- * Each letter is one of:
- * . normal character
- * b binary character
- * c control character
- */
- static void
- ichardef(s)
- char *s;
- {
- register char *cp;
- register int n;
- register char v;
-
- n = 0;
- v = 0;
- cp = chardef;
- while (*s != '\0')
- {
- switch (*s++)
- {
- case '.':
- v = 0;
- break;
- case 'c':
- v = IS_CONTROL_CHAR;
- break;
- case 'b':
- v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = (10 * n) + (s[-1] - '0');
- continue;
-
- default:
- error("invalid chardef", NULL_PARG);
- quit(1);
- /*NOTREACHED*/
- }
-
- do
- {
- if (cp >= chardef + sizeof(chardef))
- {
- error("chardef longer than 256", NULL_PARG);
- quit(1);
- /*NOTREACHED*/
- }
- *cp++ = v;
- } while (--n > 0);
- n = 0;
- }
-
- while (cp < chardef + sizeof(chardef))
- *cp++ = v;
- }
-
- /*
- * Define a charset, given a charset name.
- * The valid charset names are listed in the "charsets" array.
- */
- static int
- icharset(name)
- register char *name;
- {
- register struct charset *p;
-
- if (name == NULL || *name == '\0')
- return (0);
-
- for (p = charsets; p->name != NULL; p++)
- {
- if (strcmp(name, p->name) == 0)
- {
- ichardef(p->desc);
- return (1);
- }
- }
-
- error("invalid charset name", NULL_PARG);
- quit(1);
- /*NOTREACHED*/
- }
-
- #if HAVE_LOCALE
- /*
- * Define a charset, given a locale name.
- */
- static void
- ilocale()
- {
- register int c;
-
- setlocale(LC_CTYPE, "");
- for (c = 0; c < sizeof(chardef); c++)
- {
- if (isprint(c))
- chardef[c] = 0;
- else if (iscntrl(c))
- chardef[c] = IS_CONTROL_CHAR;
- else
- chardef[c] = IS_BINARY_CHAR|IS_CONTROL_CHAR;
- }
- }
- #endif
-
- /*
- * Define the printing format for control chars.
- */
- public void
- setbinfmt(s)
- char *s;
- {
- if (s == NULL || *s == '\0')
- s = "*s<%X>";
- /*
- * Select the attributes if it starts with "*".
- */
- if (*s == '*')
- {
- switch (s[1])
- {
- case 'd': binattr = AT_BOLD; break;
- case 'k': binattr = AT_BLINK; break;
- case 's': binattr = AT_STANDOUT; break;
- case 'u': binattr = AT_UNDERLINE; break;
- default: binattr = AT_NORMAL; break;
- }
- s += 2;
- }
- binfmt = s;
- }
-
- /*
- * Initialize charset data structures.
- */
- public void
- init_charset()
- {
- register char *s;
-
- s = getenv("LESSBINFMT");
- setbinfmt(s);
-
- /*
- * See if environment variable LESSCHARSET is defined.
- */
- s = getenv("LESSCHARSET");
- if (icharset(s))
- return;
- /*
- * LESSCHARSET is not defined: try LESSCHARDEF.
- */
- s = getenv("LESSCHARDEF");
- if (s != NULL && *s != '\0')
- {
- ichardef(s);
- return;
- }
- #if HAVE_LOCALE
- /*
- * Use setlocale.
- */
- ilocale();
- #else
- /*
- * Default to "ascii".
- */
- (void) icharset("ascii");
- #endif
- }
-
- /*
- * Is a given character a "binary" character?
- */
- public int
- binary_char(c)
- int c;
- {
- c &= 0377;
- return (chardef[c] & IS_BINARY_CHAR);
- }
-
- /*
- * Is a given character a "control" character?
- */
- public int
- control_char(c)
- int c;
- {
- c &= 0377;
- return (chardef[c] & IS_CONTROL_CHAR);
- }
-
- /*
- * Return the printable form of a character.
- * For example, in the "ascii" charset '\3' is printed as "^C".
- */
- public char *
- prchar(c)
- int c;
- {
- static char buf[8];
-
- c &= 0377;
- if (!control_char(c))
- sprintf(buf, "%c", c);
- else if (c == ESC)
- sprintf(buf, "ESC");
- else if (!control_char(c ^ 0100))
- sprintf(buf, "^%c", c ^ 0100);
- else
- sprintf(buf, binfmt, c);
- return (buf);
- }
-